package cmpe451.group7.ourcity.beans;

import java.io.IOException;
import java.io.Serializable;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import org.primefaces.context.RequestContext;
import org.springframework.transaction.annotation.Transactional;

import cmpe451.group7.ourcity.dao.UserDAO;
import cmpe451.group7.ourcity.entity.User;
import cmpe451.group7.ourcity.service.UserService;
import cmpe451.group7.ourcity.util.Utils;

/**
 * Search bean for using in the search page of the web site.
 */
@ManagedBean
@SessionScoped
public class LoginBean implements Serializable {
	private static final long serialVersionUID = 6829684192477171491L;

	@ManagedProperty(value = "#{userService}")
	private UserService userService;

	@ManagedProperty(value = "#{userDAO}")
	private UserDAO userDAO;

	// private User user;
	private long userID;
	private String name;
	private String surname;
	private String username;
	private String password;
	private boolean loggedIn;

	private boolean userInfoTextBox;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getSurname() {
		return surname;
	}

	public void setSurname(String surname) {
		this.surname = surname;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public boolean isLoggedIn() {
		return loggedIn;
	}

	public void setUserInfoTextBox(boolean userInfoTextBox) {
		this.userInfoTextBox = userInfoTextBox;
	}

	public boolean getUserInfoTextBox() {
		return this.userInfoTextBox;
	}

	public void setLoggedIn(boolean loggedIn) {
		this.loggedIn = loggedIn;
	}

	/**
	 * Checks the login information of the user and sets the loggedIn variable
	 * in this bean
	 * 
	 * @throws IOException
	 */
	@Transactional
	public void login() throws IOException {
		RequestContext context = RequestContext.getCurrentInstance();
		FacesMessage msg = null;
		loggedIn = false;

		userInfoTextBox = false;

		User user = null;
		try {
			user = getUserService().authenticate(username, password);
		} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
			e.printStackTrace();
		}

		if (user != null) {
			loggedIn = true;
			msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Welcome",
					user.getEmail());
			userID = user.getUserID();
		} else {
			userID = -1;
			loggedIn = false;
			msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Login Error",
					"Invalid credentials");
		}

		FacesContext.getCurrentInstance().addMessage(null, msg);
		context.addCallbackParam("loggedIn", loggedIn);
	}

	/**
	 * Clears the user information from the session
	 * 
	 * @throws IOException
	 */
	@Transactional
	public void logout() throws IOException {
		loggedIn = false;
		clearContent();
		Utils.reloadPage();
	}

	/**
	 * 
	 * Adds a new user to the system, then the user is automatically logged in.
	 * 
	 * @throws IOException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 */
	@Transactional
	public void register() throws IOException, NoSuchAlgorithmException,
			InvalidKeySpecException {
		RequestContext context = RequestContext.getCurrentInstance();
		FacesMessage msg = null;
		User user = userDAO.insertNewUser(name, surname, username, password);
		boolean registered = false;

		if (user != null) {
			loggedIn = true;
			registered = true;
			msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
					"Successful registration", user.getEmail());
		} else {
			loggedIn = false;
			msg = new FacesMessage(FacesMessage.SEVERITY_WARN,
					"Register Error", "Error while registering");
		}

		FacesContext.getCurrentInstance().addMessage(null, msg);
		context.addCallbackParam("registered", registered);
	}

	private void clearContent() {
		username = password = name = surname = null;
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public UserDAO getUserDAO() {
		return userDAO;
	}

	public void setUserDAO(UserDAO userDAO) {
		this.userDAO = userDAO;
	}

	public long getUserID() {
		return userID;
	}

	public void setUserID(long userID) {
		this.userID = userID;
	}
}
